1 /** 2 UDAs for decorating tests. 3 */ 4 module unit_threaded.attrs; 5 6 import unit_threaded.from; 7 8 enum UnitTest; //opt-in to registration 9 enum DontTest; //opt-out of registration 10 enum Serial; //run tests in the module in one thread / serially 11 12 alias SingleThreaded = Serial; 13 14 ///Hide test. Not run by default but can be run. 15 struct HiddenTest { 16 string reason; 17 } 18 19 /// The suite fails if the test passes. 20 struct ShouldFail { 21 string reason; 22 } 23 24 /// The suite fails unless the test throws T 25 struct ShouldFailWith(T : Throwable) { 26 alias Type = T; 27 string reason; 28 } 29 30 /// Associate a name with a unittest block. 31 struct Name { 32 string value; 33 } 34 35 /// Associates one or more tags with the test 36 struct Tags { 37 this(string[] values...) { 38 this.values = values; 39 } 40 41 this(string[] values) { 42 this.values = values; 43 } 44 45 this(string value) { 46 this.values = [value]; 47 } 48 49 string[] values; 50 } 51 52 /** Automatically assign @Tags for each parameterized test 53 e.g. 54 --------------- 55 @Values("foo", "bar") @AutoTags unittest { ... } 56 // there are now two unit tests, one for "foo" with tag "foo" 57 // and one for "bar" with tag "bar" 58 --------------- 59 */ 60 enum AutoTags; 61 62 /** Attachs these types to the a parametrized unit test. 63 The attached template function will be instantiated with 64 each type listed, e.g. 65 66 ---------------- 67 @Types!(int, byte) void testInit(T)() { T.init.shouldEqual(0); } 68 ---------------- 69 70 These would mean two testInit test runs. 71 72 Normally this would be a template but I don't know how to write 73 * the UDA code to filter a template out 74 */ 75 struct Types(T...) { 76 } 77 78 /** 79 Used as a UDA for built-in unittests to enable value-parametrized tests. 80 Example: 81 ------- 82 @Values(1, 2, 3) unittest { assert(getValue!int % 2 == 0); } 83 ------- 84 The example above results in unit_threaded running the unit tests 3 times, 85 once for each value declared. 86 87 See `getValue`. 88 */ 89 auto Values(T)(T[] values...) { 90 return ValuesImpl!T(values.dup); 91 } 92 93 auto Values(R)(R values) if (from!"std.range.primitives".isInputRange!R) { 94 import std.range.primitives : ElementType; 95 import std.array : array; 96 97 return ValuesImpl!(ElementType!R)(values.array); 98 } 99 100 struct ValuesImpl(T) { 101 T[] values; 102 } 103 104 /** 105 Retrieves the current test value of type T in a built-in unittest. 106 See `Values`. 107 */ 108 T getValue(T, int index = 0)() { 109 return ValueHolder!T.values[index]; 110 } 111 112 package struct ValueHolder(T) { 113 static T[10] values; 114 } 115 116 enum Setup; 117 enum Shutdown; 118 119 struct Flaky { 120 /// the number of times to run the test 121 enum defaultRetries = 10; 122 int retries = defaultRetries; 123 }